package edu.whut.mall.admin.shiro.realm;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import edu.whut.mall.admin.dto.ShiroSysUser;
import edu.whut.mall.admin.enums.SysStatusEnum;
import edu.whut.mall.admin.mapper.AdminMapper;
import edu.whut.mall.admin.mapper.ResourcesMapper;
import edu.whut.mall.admin.mapper.RoleMapper;
import edu.whut.mall.admin.model.Admin;
import edu.whut.mall.admin.model.Resources;
import edu.whut.mall.admin.model.Role;
import edu.whut.mall.admin.service.IAdminService;
import edu.whut.mall.admin.shiro.util.ShiroUtil;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import javax.annotation.Resource;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Author: smq
 * Unit: D9lab
 * Date: 2021-06-11 17.40
 */

@Slf4j
public class MyRealm extends AuthorizingRealm {

    @Resource
    private AdminMapper adminMapper;

    @Resource
    private ResourcesMapper resourcesMapper;

    @Resource
    private RoleMapper roleMapper;

    @Resource
    private IAdminService adminService;


    /**
     * 授权
     *
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        // 权限信息对象info,用来存放查出的用户的所有的角色（role）及权限（permission）
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        ShiroSysUser user = (ShiroSysUser) principalCollection.getPrimaryPrincipal();
        //查出用户对应的所有角色
        List<Role> roles = roleMapper.getRoleListByAdminId(user.getAdminId());
        //添加到授权信息中
        Set<String> permissionSet = new HashSet<>();
        roles.forEach(role -> {
            info.addRole(role.getName());
            //查出用户对应角色的所有权限
            List<Resources> resourcesList = resourcesMapper.getResourcesByRoleId(role.getId());
            if (!CollectionUtils.isEmpty(resourcesList)) {
                for (Resources resources : resourcesList) {
                    if (!StringUtils.isEmpty(resources.getPermission())) {
                        permissionSet.add(role.getName() + ":" + resources.getName());
                    }
                }
            }
        });
        info.setStringPermissions(permissionSet);


//        if (!CollectionUtils.isEmpty(resourcesList)) {
//            Set<String> permissionSet = new HashSet<>();
//            for (Resources resources : resourcesList) {
//                if (!StringUtils.isEmpty(resources.getPermission())) {
//                    permissionSet.add(roles.get(0).getName() + ":" + resources.getName());
//                }
//            }
//            info.setStringPermissions(permissionSet);
//        }
        return info;
    }

    /**
     * 认证
     *
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @SneakyThrows
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //获取token，即前端传入的token
        //密码认证shiro自己做，我们只需要做账号认证
//        UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken;
        String username = (String) authenticationToken.getPrincipal();
        LambdaQueryWrapper<Admin> queryWrapper = new LambdaQueryWrapper<Admin>();
        queryWrapper.eq(Admin::getUsername, username);
        Admin admin = adminMapper.selectOne(queryWrapper);
//        ShiroSysUser user = adminService.getAdminRoleByUsername(username);
        ShiroSysUser user = adminMapper.getAdminRoleListByUserName(username);
        if (admin == null) {
            throw new UnknownAccountException("账号不存在！");
        }
        if (SysStatusEnum.禁用.getCode().equals(admin.getStatus())) {
            throw new LockedAccountException("帐号已被锁定，禁止登录！");
        }
        return new SimpleAuthenticationInfo(
                user,
                admin.getPassword(),
                getName()
        );
    }

    /**
     * 清除当前用户权限缓存
     * 使用方法：在需要清除用户权限的地方注入 ShiroRealm,
     * 然后调用其 clearCache方法。
     */
    public void clearCache() {
        PrincipalCollection principals = ShiroUtil.getSubject().getPrincipals();
        super.clearCache(principals);
    }
}
